home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / custEducation / opengl1 / answers / lighting.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  11.9 KB  |  493 lines

  1. /*
  2.  * Copyright 1996, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /* lighting.c - open a window and clear the background.
  19.  *    Set up callbacks to handle keyboard input.
  20.  *      Model some objects.  Use perspective projection.
  21.  *    Use independent modeling transformations to position objects.
  22.  *    Added reshape callback to reset the viewport and viewing volume.
  23.  *    Add depth buffering.
  24.  *    Add a viewing transformation and control it using mouse input.
  25.  *
  26.  *    F1 key            - print help information
  27.  *    Left Arrow Key        - move the reference point to the left
  28.  *    Right Arrow Key        - move the reference point to the right
  29.  *    Up Arrow Key        - move the reference point up
  30.  *    Down Arrow Key        - move the reference point down
  31.  *    <f> key            - toggle front/back face culling
  32.  *    <s> key            - toggle smooth/flat shading
  33.  *    SPACE key        - generates a random background color
  34.  *    Escape Key        - exit program
  35.  */
  36. #include <GL/gl.h>
  37. #include <GL/glu.h>
  38. #include <GL/glut.h>
  39.  
  40. #include <stdio.h>
  41. #include <math.h>
  42.  
  43. /* Function Prototypes */
  44.  
  45. GLvoid initgfx( GLvoid );
  46. GLvoid keyboard( GLubyte, GLint, GLint );
  47. GLvoid specialkeys( GLint, GLint, GLint );
  48. GLvoid reshape( GLsizei, GLsizei );
  49. GLvoid drawScene( GLvoid );
  50.  
  51. void initGround( GLvoid );
  52.  
  53. void checkError( char * );
  54. void printHelp( char * );
  55.  
  56. /* Global Variables */
  57.  
  58. static GLdouble        xRef = 0.0, yRef = 0.0;
  59.  
  60. static GLfloat         green[] = { 0.0, 1.0, 0.0 };
  61. static GLfloat         darkgreen[] = { 0.0, 0.25, 0.0 };
  62. static GLfloat         red[] = { 1.0, 0.0, 0.0 };
  63. static GLfloat         magenta[] = { 1.0, 0.0, 1.0 };
  64. static GLfloat         yellow[] = { 1.0, 1.0, 0.0 };
  65. static GLfloat         blue[] = { 0.0, 0.0, 1.0 };
  66.  
  67. static GLfloat         white[] = { 1.0, 1.0, 1.0, 1.0 };
  68. static GLfloat         black[] = { 0.0, 0.0, 0.0, 0.0 };
  69.  
  70. static char *progname; 
  71.  
  72. /* Global Definitions */
  73.  
  74. #define KEY_ESC    27    /* ascii value for the escape key */
  75.  
  76. #define GRIDPOINTS    41    /* number of vertices in ground mesh */
  77.  
  78. static GLfloat     groundMesh[GRIDPOINTS][GRIDPOINTS][3] = { 0 };
  79.  
  80. void
  81. main( int argc, char *argv[] )
  82. {
  83.     GLsizei width, height;
  84.  
  85.     glutInit( &argc, argv );
  86.  
  87.     /* create a window that is 1/4 the size of the screen,
  88.      * and position it in the middle of the screen.
  89.      */
  90.     width = glutGet( GLUT_SCREEN_WIDTH ); 
  91.     height = glutGet( GLUT_SCREEN_HEIGHT );
  92.     glutInitWindowPosition( width / 4, height / 4 );
  93.     glutInitWindowSize( width / 2, height / 2 );
  94.     glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH );
  95.     glutCreateWindow( argv[0] );
  96.  
  97.     initgfx();
  98.  
  99.     glutReshapeFunc( reshape );
  100.     glutKeyboardFunc( keyboard );
  101.     glutSpecialFunc( specialkeys );
  102.     glutDisplayFunc( drawScene ); 
  103.  
  104.     progname = argv[0];
  105.  
  106.     printHelp( progname );
  107.  
  108.     glutMainLoop();
  109. }
  110.  
  111. void
  112. printHelp( char *progname )
  113. {
  114.     fprintf(stdout, 
  115.         "\n%s - create a scene and handle resizing\n\n"
  116.         "F1 key        - print help information\n"
  117.         "Left Arrow Key        - move reference point to the left\n"
  118.         "Right Arrow Key    - move reference point to the right\n"
  119.         "Up Arrow Key        - move reference point up\n"
  120.         "Down Arrow Key        - move reference point down\n"
  121.         "SPACE Key    - generates a random background color\n"
  122.         "<f> key        - toggle front/back face culling\n"
  123.         "<s> key        - toggle smooth/flat shading\n"
  124.         "Escape Key    - exit the program\n\n",
  125.         progname);
  126. }
  127.  
  128. GLvoid
  129. initgfx( GLvoid )
  130. {
  131.     /* set clear color to blue */
  132.     glClearColor( 0.0, 0.0, 1.0, 1.0 );
  133.  
  134.     /* enable the depth buffer */
  135.     glEnable( GL_DEPTH_TEST );
  136.  
  137.     /* enable the face culling */
  138.     glEnable( GL_CULL_FACE );
  139.  
  140.     initGround();
  141.  
  142.     /* Turn on the default light */
  143.     glEnable( GL_LIGHT0 );
  144.     glEnable( GL_LIGHTING );
  145.  
  146.     /* have OpenGL automatically normalize the normals,
  147.      * since we have lighting turned on and are scaling
  148.       */
  149.     glEnable( GL_NORMALIZE );
  150.  
  151.     /* Enable fast material changes for diffuse material */
  152.     glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
  153.     glEnable( GL_COLOR_MATERIAL );
  154. }
  155.  
  156. GLvoid 
  157. reshape( GLsizei width, GLsizei height )
  158. {
  159.     GLdouble    aspect;
  160.  
  161.     glViewport( 0, 0, width, height );
  162.  
  163.     /* compute aspect ratio */
  164.     aspect = (GLdouble) width / (GLdouble) height;
  165.  
  166.     glMatrixMode( GL_PROJECTION );
  167.  
  168.     /* Reset world coordinates first ... */
  169.     glLoadIdentity();
  170.  
  171.     /* Reset the viewing volume based on the new aspect ratio */
  172.     gluPerspective( 45.0, aspect, 3.0, 7.0 );
  173.  
  174.     glMatrixMode( GL_MODELVIEW );
  175. }
  176.  
  177. void 
  178. checkError( char *label )
  179. {
  180.     GLenum error;
  181.     while ( (error = glGetError()) != GL_NO_ERROR )
  182.         printf( "%s: %s\n", label, gluErrorString(error) );
  183. }
  184.  
  185. GLvoid 
  186. keyboard( GLubyte key, GLint x, GLint y )
  187. {
  188.     static GLboolean flat = GL_FALSE;
  189.     static GLboolean cullFront = GL_FALSE;
  190.  
  191.     switch (key) {
  192.     case ' ':    /* SPACE key */
  193.         /* generate a random background color */
  194.         glClearColor( drand48(), drand48(), drand48(), 1.0 ); 
  195.         glutPostRedisplay();
  196.         break;
  197.     case 'f':    /* f key */
  198.         /* toggle between back and front face culling */
  199.         cullFront = !cullFront;
  200.         if (cullFront) {
  201.             glCullFace( GL_FRONT );
  202.             printf("Culling FRONT faces\n");
  203.         } else { 
  204.             glCullFace( GL_BACK );
  205.             printf("Culling BACK faces\n");
  206.         }
  207.         glutPostRedisplay();
  208.         break;
  209.     case 's':    /* s key */
  210.         /* toggle between smooth and flat shading */
  211.         flat = !flat;
  212.         if (flat)
  213.             glShadeModel( GL_FLAT );
  214.         else 
  215.             glShadeModel( GL_SMOOTH );
  216.         glutPostRedisplay();
  217.         break;
  218.     case KEY_ESC:    /* Exit when the Escape key is pressed */
  219.         exit(0);
  220.     }
  221. }
  222.  
  223. GLvoid 
  224. specialkeys( GLint key, GLint x, GLint y )
  225. {
  226.     switch (key) {
  227.     case GLUT_KEY_F1:    /* Function key #1 */
  228.         /* print help information */
  229.         printHelp( progname );
  230.         break;
  231.  
  232.     case GLUT_KEY_LEFT:    /* move reference point to the left */
  233.         xRef -= 0.5;
  234.         if (xRef < -4.0) xRef = -4.0;
  235.         glutPostRedisplay();
  236.          break;
  237.  
  238.     case GLUT_KEY_RIGHT:    /* move reference point to the right */
  239.         xRef += 0.5;
  240.         if (xRef > 4.0) xRef = 4.0;
  241.         glutPostRedisplay();
  242.         break;
  243.  
  244.     case GLUT_KEY_UP:    /* move reference point up */
  245.         yRef += 0.5;
  246.         if (yRef > 3.0) yRef = 3.0;
  247.         glutPostRedisplay();
  248.         break;
  249.  
  250.     case GLUT_KEY_DOWN:    /* move reference point down */
  251.         yRef -= 0.5;
  252.         if (yRef < -3.0) yRef = -3.0;
  253.         glutPostRedisplay();
  254.         break;
  255.     }
  256. }
  257.  
  258. void
  259. initGround( void )
  260. {
  261.     int i, j;
  262.     GLfloat     x, y, spacing;
  263.  
  264.     /* Create a flat grid composed of points with the z value = 0 */
  265.     
  266.     /* spacing = distance between adjacent grid points in x and y */
  267.     spacing = 2.0 / (float)(GRIDPOINTS - 1);
  268.  
  269.     /* x and z range from -1.0 to 1.0 by spacing interval */
  270.     for ( x = -1.0, i = 0; i < GRIDPOINTS; x += spacing, i++ ) {
  271.         for ( y = -1.0, j = 0; j < GRIDPOINTS; y += spacing, j++ ) {
  272.             groundMesh[i][j][0] = x;
  273.             groundMesh[i][j][1] = y;
  274.             groundMesh[i][j][2] = 0.0;
  275.         }
  276.     }
  277. }
  278.  
  279. GLvoid
  280. drawGround( GLvoid )
  281. {
  282.     register int i, j;
  283.  
  284.     glNormal3f( 0.0, 0.0, 1.0 );
  285.     
  286.     /* Draw quad strips connecting grid points. 
  287.      * Grid is drawn column by column, 
  288.      * where each column is one quad strip.
  289.      * Every pair of vertices after first two vertices
  290.      * adds a new quad to the strip.
  291.      */
  292.     for ( i = 0; i < (GRIDPOINTS - 1); i++ ) {
  293.         glBegin( GL_QUAD_STRIP );
  294.         for ( j = 0; j < (GRIDPOINTS); j++ ) {
  295.             glColor3f( 0.0, 1.0 - (GLfloat) j/GRIDPOINTS, 0.0 );
  296.             glVertex3fv( &groundMesh[i][j][0] );
  297.             glVertex3fv( &groundMesh[i + 1][j][0] );
  298.         }
  299.         glEnd();
  300.     }
  301. }
  302.  
  303. GLvoid
  304. drawWindow()
  305. {
  306.     /* window */
  307.     static GLfloat v0[] = { 0.0, 0.4 };
  308.     static GLfloat v1[] = { 0.0, 0.0 };
  309.     static GLfloat v2[] = { 0.1, 0.4 };
  310.     static GLfloat v3[] = { 0.1, 0.0 };
  311.     static GLfloat v4[] = { 0.2, 0.4 };
  312.     static GLfloat v5[] = { 0.2, 0.0 };
  313.  
  314.     /* draw 2 quadrilateral strip to make a window */
  315.     glNormal3f( 0.0, 0.0, 1.0 );
  316.     glBegin( GL_QUAD_STRIP );
  317.         glColor3f( 1.0, 0.0, 0.0 );
  318.         glVertex2fv (v0);
  319.         glColor3f( 0.9, 0.0, 1.0 );
  320.         glVertex2fv (v1);
  321.         glColor3f( 0.8, 0.1, 0.0 );
  322.         glVertex2fv (v2);
  323.         glColor3f( 0.7, 0.2, 1.0 );
  324.         glVertex2fv (v3);
  325.         glColor3f( 0.6, 0.3, 0.0 );
  326.         glVertex2fv (v4);
  327.         glColor3f( 0.5, 0.4, 1.0 );
  328.         glVertex2fv (v5);
  329.         glColor3f( 0.4, 0.5, 0.0 );
  330.     glEnd();
  331. }
  332.  
  333. /* draw a "circle" using a triangle fan; set the
  334.  * center of the circle to white, and the outside
  335.  * to the color passed in
  336.  */
  337. GLvoid
  338. drawFan( GLfloat *color )
  339. {
  340.     /* Draw a triangle fan centered at the current coordinate
  341.      * system origin 
  342.      */
  343.     glNormal3f( 0.0, 0.0, 1.0 );
  344.     glBegin( GL_TRIANGLE_FAN );
  345.         glColor3f( 1.0, 1.0, 1.0 );
  346.         glVertex2f( 0.0, 0.0 );
  347.         glColor3fv( color );
  348.         glVertex2f( 0.0, -0.2 );
  349.         glVertex2f( 0.2, -0.1 );
  350.         glVertex2f( 0.2, 0.1 );
  351.         glVertex2f( 0.0, 0.2 );
  352.         glVertex2f( -0.2, 0.1 );
  353.         glVertex2f( -0.2, -0.1 );
  354.         glVertex2f( 0.0, -0.2 );
  355.     glEnd();
  356. }
  357.  
  358. /* draw a flower with the base of the stem 
  359.  * at the current location 
  360.  */
  361. GLvoid
  362. drawFlower( GLfloat *color )
  363. {
  364.     /* draw the stem with 2 leaves */
  365.     glColor3fv( darkgreen );
  366.     glNormal3f( 0.0, 0.0, 1.0 );
  367.     glBegin( GL_LINES );
  368.         glVertex2f( 0.0, 0.0 );         /* stem */
  369.         glVertex2f( 0.0, 0.25 );
  370.         glVertex2f( 0.0, 0.1 );         /* leaf */
  371.         glVertex2f( 0.05, 0.15 ); 
  372.         glVertex2f( 0.0, 0.05 );     /* leaf */
  373.         glVertex2f( -0.05, 0.2 );
  374.     glEnd();
  375.  
  376.     glPushMatrix();
  377.         /* move to the top of the stem */
  378.         glTranslatef( 0.0, 0.25, 0.0 );
  379.  
  380.         /* use a scaled triangle fan for the flower head */
  381.         glScalef( 0.1, 0.1, 1.0 );
  382.         drawFan( color );  
  383.     glPopMatrix();
  384. }
  385.  
  386. /* draw a house centered at the current origin;
  387.  * the bounding box for the house is 1.0 x 2.0 units
  388.  */
  389. GLvoid
  390. drawHouse()
  391. {
  392.     /* draw a 3D house */
  393.     glColor3f( 1.0, 1.0, 1.0 ); /* white */
  394.     SolidBox( 1.0, 1.5, 1.0 );
  395.  
  396.     glPushMatrix();
  397.         /* move to the peak of the roof */
  398.         glTranslatef( 0.0, 1.25, 0.0 );
  399.  
  400.         /* draw a triangle fan for the roof */
  401.         glColor3f( 0.0, 0.0, 0.0 ); /* black */
  402.         glNormal3f( 0.0, 1.0, 1.0 );
  403.         glBegin( GL_TRIANGLE_FAN );
  404.             glVertex3f( 0.0, 0.0, 0.0 ); /* peak */
  405.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  406.             glVertex3f( 0.5, -0.5, 0.5 ); /* front right */
  407.             glVertex3f( 0.5, -0.5, -0.5 ); /* back right */
  408.             glVertex3f( -0.5, -0.5, -0.5 ); /* back left */
  409.             glVertex3f( -0.5, -0.5, 0.5 ); /* front left */
  410.         glEnd();
  411.     glPopMatrix();
  412.  
  413.     glPushMatrix();
  414.         /* move to just in front of the house */
  415.         glTranslatef( 0.0, 0.0, 0.50001 );
  416.  
  417.         /* draw the door */
  418.         glColor3f( 0.5, 0.2, 0.1 ); /* brown */
  419.         glNormal3f( 0.0, 0.0, 1.0 );
  420.         glRectf( -0.2, -0.75, 0.2, 0.0 );
  421.  
  422.         glPushMatrix();
  423.             /* move to the location for the left window */
  424.             glTranslatef( -0.4, 0.2, 0.0 );
  425.             drawWindow();
  426.         glPopMatrix();
  427.  
  428.         glPushMatrix();
  429.             /* move to the location for the right window */
  430.             glTranslatef( 0.2, 0.2, 0.0 );
  431.             drawWindow();
  432.         glPopMatrix();
  433.     glPopMatrix();
  434. }
  435.  
  436. GLvoid
  437. drawScene( GLvoid )
  438. {
  439.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  440.  
  441.     glPushMatrix();
  442.  
  443.         /* Move the reference point */
  444.         gluLookAt( 0.0, 0.0, 4.0, xRef, yRef, 0.0, 0.0, 1.0, 0.0 );
  445.  
  446.         /* draw the ground as a quad mesh so that it will
  447.          * be lit properly
  448.          */
  449.         glPushMatrix();
  450.             glTranslatef( 0.0, -1.0, 0.0 );
  451.             glRotatef( -45.0, 1.0, 0.0, 0.0 );
  452.             glScalef( 3.0, 1.0, 1.0 );
  453.             drawGround();
  454.         glPopMatrix();
  455.  
  456.         /* draw the house */
  457.         glPushMatrix();
  458.             /* move to where the center of the house should be */
  459.             glTranslatef( -0.5, 0.0, 0.0 );
  460.  
  461.             /* shrink the house slightly */
  462.             glScalef( 0.7, 0.7, 0.7 );
  463.             drawHouse();
  464.         glPopMatrix();
  465.  
  466.         /* draw the sun */
  467.         glPushMatrix();
  468.             /* move to the location of the sun */
  469.             glTranslatef( 2.0, 2.0, -1.5 );
  470.             glColor3fv( yellow );
  471.             glutSolidSphere( 0.2, 8, 15 );
  472.         glPopMatrix();
  473.  
  474.         /* draw several tulips in the foreground */
  475.         glPushMatrix();
  476.             glTranslatef( 1.0, -1.0, 1.0 );
  477.             drawFlower( red );
  478.             glTranslatef( 0.0, 0.0, -0.5 );
  479.             drawFlower( yellow );
  480.         glPopMatrix();
  481.         glPushMatrix();
  482.             glTranslatef( -1.0, -1.0, 1.0 );
  483.             drawFlower( blue );
  484.             glTranslatef( 0.0, 0.0, -0.5 );
  485.             drawFlower( magenta );
  486.         glPopMatrix();
  487.  
  488.     glPopMatrix();
  489.  
  490.     checkError( "drawScene" );
  491.     glFlush();
  492. }
  493.